package com.framework.base.aqs;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author chaolong.jin
 * @description
 * @date 2019/07/01 09:36
 */
public class ThreadStatusTest extends Thread {
    private int i;
    private static ReentrantLock lock = new ReentrantLock();
    private static Condition providerCondition = lock.newCondition();
    private static Condition consumerCondition = lock.newCondition();

    private static List<Integer> goods = new ArrayList<>();
    private static BlockingQueue<Integer> blockingQueue = new ArrayBlockingQueue<Integer>(10);

    public static void main(String[] args) {


//        Thread provider = new ProviderThread();
//        Thread consumer = new ConsumerThread(1);
//        Thread a = new ConsumerThread(2);
//        Thread b = new ConsumerThread(3);
//        provider.start();
//        consumer.start();
//        a.start();
//        b.start();
        for (int i = 0; i < 5; i++) {
            BlockProvider thread = new BlockProvider();
            thread.start();
        }
        for (int i = 0; i < 10; i++) {
            BlockConsumer blockConsumer = new BlockConsumer();
            blockConsumer.start();
        }


    }

    @Override
    public void run() {

        threadMethod(i);
    }

    public ThreadStatusTest(int i) {
        this.i = i;
    }

    private void threadMethod(int i) {
        try {
            while (!lock.tryLock()) {
            }
            System.out.println(Thread.currentThread().getName() + "Running" + "====" + i + "===getLock");
            for (int j = 0; j < 10; j++) {
                Thread.sleep(1000);
                if (!lock.isLocked()) {
                    continue;
                }
                if (j == 3) {
                    wait();
                    return;
                }
                System.out.println("running");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    static class ProviderThread extends Thread {
        @Override
        public void run() {
            lock.lock();
            System.out.println("Provider Lock");
            try {
                while (true) {

                    while (goods.isEmpty()) {
                        Random random = new Random();
                        int num = random.nextInt(1000);
                        goods.add(num);
                        Thread.sleep(1000);
                        System.out.println("Provider goods==" + num);
                    }
                    providerCondition.await();
                    consumerCondition.signal();
                }
//                condition.wait();
            } catch (InterruptedException e) {
            } finally {

                lock.unlock();
            }
        }
    }

    static class ConsumerThread extends Thread {
        private int i;

        public ConsumerThread(int i) {
            this.i = i;
        }

        @Override
        public void run() {
            try {
                lock.lock();
                while (true) {
                    System.out.println(Thread.currentThread().getName() + " Consumer Lock");
                    if (goods.isEmpty()) {
                        consumerCondition.await();
                    }
                    int num = goods.remove(0);
                    System.out.println(i + "   ==Consumer==" + num);
                    Thread.sleep(1000);
                    providerCondition.signal();

                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }

        }
    }

    static class BlockProvider extends Thread {

        @Override
        public void run() {
            while (true) {
                Random random = new Random();
                int num = random.nextInt(1000);
                try {
                    blockingQueue.put(num);
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + " Provider" + num);
            }


        }
    }

    static class BlockConsumer extends Thread {

        @Override
        public void run() {
            while (true) {
                try {
                    int num = blockingQueue.take();
                    Thread.sleep(1000);
                    System.out.println(Thread.currentThread().getName() + "take" + num);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }

        }
    }
}
